<?php

namespace maotool\core;

use maotool\core\config\ProxyConfig;
use maotool\object\ObjUtil;
use maotool\util\ArrayUtil;
use maotool\util\TreeUtil;

class Config
{

    /**
     * 配置参数数据
     * @var array
     */
    protected $data = [];

    /**
     * 检测配置是否存在
     * @access public
     * @param string $name 配置参数名（支持多级配置 .号分割）
     * @return bool
     */
    public function has($name)
    {
        return !is_null($this->get($name));
    }


    /**
     * 获取配置参数 为空则获取所有配置
     * @access public
     * @param string|null $name 配置参数名（支持多级配置 .号分割）
     * @param mixed|null $default 默认值
     * @return mixed
     */
    public function get($name = null, $default = null)
    {
        $data = $this->data;
        $loadProxyConfig = function ($data) {
            return TreeUtil::recursion($data, function ($data, $next) {
                if ($data instanceof ProxyConfig) {
                    $data = $data->get();
                }
                if (isset($data) && is_array($data)) {
                    $result = array_map(function ($value) use ($next) {
                        return $next($value, $value);
                    }, $data);
                } else {
                    $result = $data;
                }
                return $result;
            });
        };
        if (ObjUtil::isNotNull($name)) {
            if (is_string($name)) {
                $name = explode(".", $name);
                foreach ($name as $index => $item) {
                    if (isset($data[$item])) {
                        if ($data[$item] instanceof ProxyConfig) {
                            $data[$item] = $loadProxyConfig($data[$item]);
                        }
                        if (is_array($data[$item])) {
                            if (ArrayUtil::keyNotExists($item, $data)) {
                                if (ObjUtil::isNull($default)) {
                                    return null;
                                } else {
                                    if (($index + 1) == count($name)) {
                                        $data[$item] = null;
                                    } else {
                                        $data[$item] = [];
                                    }
                                }
                            }
                        }
                        $data = &$data[$item];
                    } else {
                        $data = null;
                    }
                }
            }
        }
        if (is_null($data)) {
            $data = $loadProxyConfig($default);
        } else {
            $data = $loadProxyConfig($data);
        }
        return $data;
    }

    /**
     * 设置配置参数值
     * @access public
     * @param string $name 配置参数名
     * @param mixed|null $next 配置值
     * @return bool
     */
    public function setProxy($name, $next)
    {
        return self::set($name, new ProxyConfig($next));
    }

    /**
     * 设置配置参数值
     * @access public
     * @param string $name 配置参数名
     * @param mixed|null $value 配置值
     * @return bool
     */
    public function set($name, $value = null)
    {
        $name = explode(".", $name);
        $data = &$this->data;
        foreach ($name as $index => $item) {
            if (ArrayUtil::keyNotExists($item, $data)) {
                if (($index + 1) == count($name)) {
                    $data[$item] = null;
                } else {
                    $data[$item] = [];
                }
            }
            $data = &$data[$item];
        }
        if (ObjUtil::equals($data, $value)) {
            $data = $value;
            return false;
        } else {
            $data = $value;
            return true;
        }
    }

    /**
     * 移除配置
     * @access public
     * @param string $name 配置参数名（支持多级配置 .号分割）
     * @return bool
     */
    public function remove($name)
    {
        $name = explode(".", $name);
        $data = &$this->data;
        foreach ($name as $index => $item) {
            if (ArrayUtil::keyNotExists($item, $data)) {
                return false;
            }
            if (($index + 1) == count($name)) {
                unset($data[$item]);
                return true;
            }
            $data = &$data[$item];
        }
        return false;
    }

    /**
     * 重置配置参数
     * @access public
     * @return void
     */
    public function reset()
    {
        $this->data = [];
    }

    /**
     * 设置配置
     * @access public
     * @param string $name 参数名
     * @param mixed $value 值
     */
    public function __set($name, $value)
    {
        return $this->set($name, $value);
    }

    /**
     * 获取配置参数
     * @access public
     * @param string $name 参数名
     * @return mixed
     */
    public function __get($name)
    {
        return $this->get($name);
    }

    /**
     * 检测是否存在参数
     * @access public
     * @param string $name 参数名
     * @return bool
     */
    public function __isset($name)
    {
        return $this->has($name);
    }

    /**
     * 配置转为字符串
     * @return string
     */
    public function __tostring()
    {
        return json_encode($this->data);
    }

}
